package dingtalk

import (
	"bytes"
	"fmt"
	"gitee.com/tjloved/tool/helper"
	"github.com/pkg/errors"
	"net/http"
	"sync"
)

type DingTalk struct {
	AccessToken string
	Keyword     string
}

var dingTalkMap sync.Map

func New(config ...string) *DingTalk {
	configName := "default"
	if len(config) > 0 {
		configName = config[0]
	}
	way.Config().GetStringMapString(configName)
	if _, ok := dingTalkMap.Load(configName); !ok {
		configMap := way.Config().GetStringMapString("dingtalk." + configName)
		dingTalkMap.Store(configName, Get(configMap))
	}
	c, _ := dingTalkMap.Load(configName)
	if client, ok := c.(*DingTalk); ok {
		return client
	} else {
		panic("钉钉机器人初始化错误")
	}
}

func Get(configMap map[string]string) *DingTalk {
	return &DingTalk{
		AccessToken: configMap["access_token"],
		Keyword:     configMap["keyword"],
	}
}

func (d *DingTalk) Send(message Message) error {
	if body, err := message.ToJson(d.Keyword); err != nil {
		return err
	} else {
		if err := d.Request(body); err != nil {
			return err
		}
	}
	return nil
}

func (d *DingTalk) SendSimpleText(content string) error {
	text := NewText()
	text.Content(content)
	return d.Send(text)
}

type Response struct {
	ErrCode int    `json:"errcode"`
	ErrMsg  string `json:"errmsg"`
}

func (d *DingTalk) Request(data []byte) error {
	bts := bytes.NewReader(data)
	webhook := fmt.Sprintf("https://oapi.dingtalk.com/robot/send?access_token=%s", d.AccessToken)
	request, _ := http.NewRequest("POST", webhook, bts)
	request.Header.Add("Content-Type", " application/json")
	client := &http.Client{}
	response, err := client.Do(request)
	_ = response.Body.Close()
	if err != nil {
		return errors.WithMessagef(err, "钉钉消息推送失败: %v \n %s", webhook, data)
	}

	if response.StatusCode != http.StatusOK {
		return errors.WithMessagef(err, "钉钉消息推送失败: %v %v %s", webhook, response.StatusCode, data)
	}
	var res Response
	if err, _ := helper.HttpParseBodyWithResponseString(response, &res); err != nil {
		return errors.WithMessagef(err, "钉钉消息接口返回数据解析错误: %s \n", webhook)
	}
	return nil
}

//func (d *DingTalk) sign(timestamp string) string {
//	signString := d.Secret + "\n" + timestamp
//	hmacH := hmac.New(sha256.New, []byte(d.Secret))
//	hmacH.Write([]byte(signString))
//	hashStr := hmacH.Sum(nil)
//	sign := url.QueryEscape(base64.StdEncoding.EncodeToString(hashStr))
//	return sign
//}
